package com.tgm.utils;

import com.tgm.domain.vo.PortraitVO;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class ConsumptionDataConverter {

    // 日期格式化工具（处理消费时间）
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 将用户消费记录转换为结构化文本，供AI生成消费画像
     */
    public String convertUserConsumptionToText(String userId, List<PortraitVO> records) {
        if (records.isEmpty()) {
            return "用户ID：" + userId + "，在查询时间范围内无消费记录。";
        }

        // 1. 基础信息（用户名、部门、年级）
        PortraitVO firstRecord = records.get(0);
        String baseInfo = String.format(
                "用户ID：%s，用户名：%s，学院：%s，年级：%s。",
                userId,
                firstRecord.getUserName() != null ? firstRecord.getUserName() : "未知",
                firstRecord.getDepartment() != null ? firstRecord.getDepartment() : "未知",
                firstRecord.getGrade() != null ? firstRecord.getGrade() : "未知"
        );

        // 2. 时间范围与总消费统计
        Date minTime = records.stream().map(PortraitVO::getConsumeTime).min(Date::compareTo).get();
        Date maxTime = records.stream().map(PortraitVO::getConsumeTime).max(Date::compareTo).get();
        long dayCount = (maxTime.getTime() - minTime.getTime()) / (1000 * 60 * 60 * 24) + 1; // 总天数
        int totalCount = records.size(); // 总消费次数
        BigDecimal totalAmount = records.stream()
                .map(PortraitVO::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add); // 总消费金额
        BigDecimal avgAmount = totalCount > 0 ? totalAmount.divide(new BigDecimal(totalCount), 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;

        String timeAndTotal = String.format(
                "消费时间范围：%s 至 %s（共%d天），总消费%d次，总金额%.2f元，平均每次%.2f元。",
                DATE_FORMAT.format(minTime),
                DATE_FORMAT.format(maxTime),
                dayCount,
                totalCount,
                totalAmount,
                avgAmount
        );

        // 3. 消费频率（每周几次 + 工作日/周末差异）
        double weekCount = dayCount / 7.0; // 总周数
        double weeklyFreq = weekCount > 0 ? Math.round(totalCount / weekCount * 10) / 10.0 : 0; // 每周次数（保留1位小数）

        // 统计工作日（1-5）和周末（6-7）的消费次数（Calendar.SUNDAY=1，SATURDAY=7）
        long weekdayCount = 0;
        long weekendCount = 0;
        for (PortraitVO record : records) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(record.getConsumeTime());
            int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
            if (dayOfWeek >= 2 && dayOfWeek <= 6) { // 周一（2）至周五（6）为工作日
                weekdayCount++;
            } else { // 周日（1）、周六（7）为周末
                weekendCount++;
            }
        }
        String freqText = String.format(
                "消费频率：每周约%.1f次。工作日消费%d次，周末消费%d次。",
                weeklyFreq,
                weekdayCount,
                weekendCount
        );

        // 4. 消费类型偏好（占比）
        Map<String, Long> typeCountMap = records.stream()
                .filter(r -> r.getMerchantType() != null)
                .collect(Collectors.groupingBy(
                        PortraitVO::getMerchantType,
                        Collectors.counting()
                ));
        // 按次数排序，取前3种类型
        List<Map.Entry<String, Long>> sortedTypes = new ArrayList<>(typeCountMap.entrySet());
        sortedTypes.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
        String typeRatioText = sortedTypes.stream()
                .map(entry -> String.format(
                        "%s（%d次，占比%.0f%%）",
                        entry.getKey(),
                        entry.getValue(),
                        entry.getValue() * 100.0 / totalCount
                ))
                .collect(Collectors.joining("、"));

        // 5. 时段偏好（早/中/晚）
        long morningCount = 0; // 6:00-11:59
        long afternoonCount = 0; // 12:00-17:59
        long eveningCount = 0; // 18:00-21:59
        long nightCount = 0; // 22:00-5:59
        for (PortraitVO record : records) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(record.getConsumeTime());
            int hour = cal.get(Calendar.HOUR_OF_DAY);
            if (hour >= 6 && hour < 12) {
                morningCount++;
            } else if (hour >= 12 && hour < 18) {
                afternoonCount++;
            } else if (hour >= 18 && hour < 22) {
                eveningCount++;
            } else {
                nightCount++;
            }
        }
        String timePeriodText = String.format(
                "时段偏好：上午（6:00-11:59）%d次、下午（12:00-17:59）%d次、晚上（18:00-21:59）%d次、凌晨（22:00-5:59）%d次。",
                morningCount, afternoonCount, eveningCount, nightCount
        );

        // 6. 常去商铺（次数前3）
        Map<String, Long> merchantCountMap = records.stream()
                .filter(r -> r.getMerchantName() != null)
                .collect(Collectors.groupingBy(
                        PortraitVO::getMerchantName,
                        Collectors.counting()
                ));
        List<Map.Entry<String, Long>> sortedMerchants = new ArrayList<>(merchantCountMap.entrySet());
        sortedMerchants.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
        String topMerchants = sortedMerchants.stream()
                .limit(3)
                .map(entry -> entry.getKey() + "（" + entry.getValue() + "次）")
                .collect(Collectors.joining("、"));
        String merchantText = "常去商铺：" + (topMerchants.isEmpty() ? "无" : topMerchants);

        // 7. 异常消费行为
        List<PortraitVO> abnormalRecords = records.stream()
                .filter(r -> r.getAbnormalReason() != null && !r.getAbnormalReason().isEmpty())
                .collect(Collectors.toList());
        String abnormalText;
        if (abnormalRecords.isEmpty()) {
            abnormalText = "无异常消费记录。";
        } else {
            // 提取异常原因和时间
            String abnormalDetails = abnormalRecords.stream()
                    .map(r -> String.format(
                            "%s（%s，金额%.2f元，原因：%s）",
                            DATE_FORMAT.format(r.getConsumeTime()),
                            r.getMerchantName(),
                            r.getAmount(),
                            r.getAbnormalReason()
                    ))
                    .collect(Collectors.joining("；"));
            abnormalText = String.format("异常消费共%d次：%s", abnormalRecords.size(), abnormalDetails);
        }

        // 拼接所有信息（结构化文本）
        return String.join("\n",
                baseInfo,
                timeAndTotal,
                freqText,
                "消费类型偏好：" + typeRatioText,
                timePeriodText,
                merchantText,
                abnormalText
        );
    }
    /**
     * 动态转换群体消费记录为结构化文本（支持学院/年级多维度）
     * 规则：
     * - 若department和grade均不为空：分析「某学院某年级」的整体消费
     * - 若department为空、grade不为空：分析「某年级下各学院」的消费对比
     * - 若grade为空、department不为空：分析「某学院下各年级」的消费对比
     */
    public String convertUserConsumptionToText(String department, String grade, List<PortraitVO> records) {
        if (records.isEmpty()) {
            String groupDesc = getGroupDescription(department, grade);
            return groupDesc + "中暂无消费记录。";
        }

        // 1. 基础时间与总消费统计
        Date minTime = records.stream().map(PortraitVO::getConsumeTime).min(Date::compareTo).get();
        Date maxTime = records.stream().map(PortraitVO::getConsumeTime).max(Date::compareTo).get();
        long dayCount = (maxTime.getTime() - minTime.getTime()) / (1000 * 60 * 60 * 24) + 1;
        int totalCount = records.size();
        BigDecimal totalAmount = records.stream()
                .map(PortraitVO::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 2. 构建群体描述与基础信息
        String groupDesc = getGroupDescription(department, grade);
        String baseInfo = String.format(
                "%s\n消费时间范围：%s 至 %s（共%d天）\n总消费次数：%d次，总消费金额：%.2f元",
                groupDesc,
                DATE_FORMAT.format(minTime),
                DATE_FORMAT.format(maxTime),
                dayCount,
                totalCount,
                totalAmount
        );

        // 3. 按维度拆分群体（核心动态逻辑）
        String dimensionData;
        if (department != null && grade != null) {
            // 场景1：某学院某年级（整体分析）
            dimensionData = analyzeSingleGroup(records);
        } else if (department == null && grade != null) {
            // 场景2：某年级下各学院（对比分析）
            Map<String, List<PortraitVO>> deptGroups = records.stream()
                    .collect(Collectors.groupingBy(PortraitVO::getDepartment));
            dimensionData = analyzeMultiGroups("学院", deptGroups);
        } else if (department != null) {
            // 场景3：某学院下各年级（对比分析）
            Map<String, List<PortraitVO>> gradeGroups = records.stream()
                    .collect(Collectors.groupingBy(PortraitVO::getGrade));
            dimensionData = analyzeMultiGroups("年级", gradeGroups);
        } else {
            // 特殊情况：均为空（全量数据，按学院+年级分组）
            Map<String, List<PortraitVO>> allGroups = records.stream()
                    .collect(Collectors.groupingBy(vo -> vo.getDepartment() + "-" + vo.getGrade()));
            dimensionData = analyzeMultiGroups("学院-年级", allGroups);
        }

        // 4. 拼接所有信息
        return baseInfo + "\n" + dimensionData;
    }

    // 辅助方法：生成群体描述文本
    private String getGroupDescription(String department, String grade) {
        if (department != null && grade != null) {
            return "群体：" + department + grade + "级";
        } else if (department == null && grade != null) {
            return "群体：" + grade + "级（包含各学院）";
        } else if (department != null) {
            return "群体：" + department + "（包含各年级）";
        } else {
            return "群体：全量用户（按学院-年级划分）";
        }
    }

    // 分析单一群体（某学院某年级）的消费特征
    private String analyzeSingleGroup(List<PortraitVO> records) {
        int totalCount = records.size();
        // 消费类型占比
        Map<String, Long> typeMap = records.stream()
                .filter(vo -> vo.getMerchantType() != null)
                .collect(Collectors.groupingBy(PortraitVO::getMerchantType, Collectors.counting()));
        String topTypes = getTopItems(typeMap, 3, "消费类型");

        // 时段分布
        Map<String, Long> periodMap = getPeriodDistribution(records);
        String periodDist = periodMap.entrySet().stream()
                .map(e -> e.getKey() + "（" + e.getValue() + "次，占比" + Math.round(e.getValue() * 100.0 / totalCount) + "%）")
                .collect(Collectors.joining("、"));

        // 常去商铺
        Map<String, Long> merchantMap = records.stream()
                .filter(vo -> vo.getMerchantName() != null)
                .collect(Collectors.groupingBy(PortraitVO::getMerchantName, Collectors.counting()));
        String topMerchants = getTopItems(merchantMap, 3, "商铺");

        // 异常消费
        long abnormalCount = records.stream()
                .filter(vo -> vo.getAbnormalReason() != null && !vo.getAbnormalReason().isEmpty())
                .count();
        String abnormalText = abnormalCount > 0
                ? "异常消费：共" + abnormalCount + "次（占比" + Math.round(abnormalCount * 100.0 / totalCount) + "%）"
                : "异常消费：无";

        return String.join("\n",
                "核心特征：",
                "- 消费类型：" + topTypes,
                "- 时段分布：" + periodDist,
                "- 常去商铺：" + topMerchants,
                "- " + abnormalText
        );
    }

    // 分析多群体（如某年级下的各学院）的对比特征
    private String analyzeMultiGroups(String dimensionName, Map<String, List<PortraitVO>> groupMap) {
        // 按消费次数排序群体
        List<Map.Entry<String, List<PortraitVO>>> sortedGroups = new ArrayList<>(groupMap.entrySet());
        sortedGroups.sort((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size()));

        // 生成每个子群体的核心特征
        StringBuilder sb = new StringBuilder();
        sb.append("按").append(dimensionName).append("拆分分析：\n");
        for (Map.Entry<String, List<PortraitVO>> entry : sortedGroups) {
            String groupName = entry.getKey() == null ? "未知" + dimensionName : entry.getKey();
            List<PortraitVO> groupRecords = entry.getValue();
            int groupCount = groupRecords.size();

            // 子群体消费类型TOP1
            Map<String, Long> typeMap = groupRecords.stream()
                    .filter(vo -> vo.getMerchantType() != null)
                    .collect(Collectors.groupingBy(PortraitVO::getMerchantType, Collectors.counting()));
            String topType = typeMap.isEmpty() ? "无" :
                    typeMap.entrySet().stream()
                            .max(Map.Entry.comparingByValue())
                            .get().getKey();

            // 子群体消费占比（相对总群体）
            int totalAll = sortedGroups.stream().mapToInt(e -> e.getValue().size()).sum();
            int ratio = (int) Math.round(groupCount * 100.0 / totalAll);

            sb.append(String.format("- %s：消费%d次（占比%d%%），偏好%s，常去%s%n",
                    groupName,
                    groupCount,
                    ratio,
                    topType.isEmpty() ? "无" : topType,
                    getTopItems(getMerchantMap(groupRecords), 1, "")));
        }
        return sb.toString();
    }

    // 辅助方法：统计时段分布（上午/下午/晚上/凌晨）
    private Map<String, Long> getPeriodDistribution(List<PortraitVO> records) {
        Map<String, Long> periodMap = new HashMap<>();
        periodMap.put("上午（6:00-11:59）", 0L);
        periodMap.put("下午（12:00-17:59）", 0L);
        periodMap.put("晚上（18:00-21:59）", 0L);
        periodMap.put("凌晨（22:00-5:59）", 0L);

        for (PortraitVO vo : records) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(vo.getConsumeTime());
            int hour = cal.get(Calendar.HOUR_OF_DAY);
            if (hour >= 6 && hour < 12) {
                periodMap.put("上午（6:00-11:59）", periodMap.get("上午（6:00-11:59）") + 1);
            } else if (hour >= 12 && hour < 18) {
                periodMap.put("下午（12:00-17:59）", periodMap.get("下午（12:00-17:59）") + 1);
            } else if (hour >= 18 && hour < 22) {
                periodMap.put("晚上（18:00-21:59）", periodMap.get("晚上（18:00-21:59）") + 1);
            } else {
                periodMap.put("凌晨（22:00-5:59）", periodMap.get("凌晨（22:00-5:59）") + 1);
            }
        }
        return periodMap;
    }

    // 辅助方法：获取TOP N的类型/商铺
    private String getTopItems(Map<String, Long> countMap, int topN, String itemName) {
        if (countMap.isEmpty()) {
            return "无" + itemName;
        }
        List<Map.Entry<String, Long>> sorted = new ArrayList<>(countMap.entrySet());
        sorted.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
        return sorted.stream()
                .limit(topN)
                .map(e -> e.getKey() + "（" + e.getValue() + "次）")
                .collect(Collectors.joining("、"));
    }

    // 辅助方法：获取商铺消费次数Map
    private Map<String, Long> getMerchantMap(List<PortraitVO> records) {
        return records.stream()
                .filter(vo -> vo.getMerchantName() != null)
                .collect(Collectors.groupingBy(PortraitVO::getMerchantName, Collectors.counting()));
    }
}